package org.uninova.mobis.servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.uninova.mobis.api.interfaces.open.geolocation.NominatimGeolocationInterface;
import org.uninova.mobis.pojos.Coordinate;
import org.uninova.mobis.pojos.NominatimAddress;

import com.google.gson.Gson;

/**
 * Servlet implementation class GetNominatimGeocodingServlet
 */
@WebServlet("/GetNominatimGeocoding")
public class GetNominatimGeocodingServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public GetNominatimGeocodingServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		processRequest(request, response) ;
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		processRequest(request, response) ;
	}
	
	
	/**
	 * This servlet executes both reverse and normal geocoding operations
	 * 
	 * @param isReverse		Boolean stating if the operation is reverse geocoding (true) or normal geocoding (false)
	 * @param coord			In the case of reverse geocoding, the WSG84 coordinate of the location to get the address for
	 * @param query			In the case of normal geocoding, the address of the location to get the coordinate for
	 * 
	 * @return				In case of reverse geocoding, the output is the address for the location; in case of normal geocoding, the output is the coordinate for the location
	 */
	private void processRequest(HttpServletRequest request, HttpServletResponse response) {
		
		String jsonResponse = "" ;
		boolean isReverse = Boolean.parseBoolean(request.getParameter("isReverse")) ;
		
		NominatimGeolocationInterface nominatimInterface = new NominatimGeolocationInterface() ;
		Gson gson = new Gson() ;
		
		if (isReverse) {
			String coord = request.getParameter("coord") ;
			double lat = Double.parseDouble(coord.substring(0, coord.indexOf(","))) ;
			double lng = Double.parseDouble(coord.substring(coord.indexOf(",") + 1)) ;
			jsonResponse = this.nominatimReverseGeocoding(lat, lng, nominatimInterface, gson) ;
		}
		else {
			String query = request.getParameter("query") ;
			jsonResponse = this.nominatimGeocoding(query, nominatimInterface, gson) ;
		}
		
		
		
		PrintWriter out;
		try {
			out = response.getWriter() ;
			out.println(jsonResponse) ;
			out.close() ;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private String nominatimGeocoding(String query, NominatimGeolocationInterface nominatimInterface, Gson gson) {
		
		ArrayList<Coordinate> geocodedCoords = nominatimInterface.geocoding(true, query, "", "", "", "", "", null, true, null, 1) ;
		
		String jsonResponse = gson.toJson(geocodedCoords) ;
		
		return jsonResponse ;
	}
	
	private String nominatimReverseGeocoding(double lat, double lng, NominatimGeolocationInterface nominatimInterface, Gson gson) {
		NominatimAddress addr = nominatimInterface.reverseGeocoding(lat, lng, "", "", 17, true) ;
		
		String jsonResponse = gson.toJson(addr) ;
		
		return jsonResponse ;
	}

}
